package com.googlecode.vmock;

import java.lang.reflect.AccessibleObject;

import com.googlecode.vmock.matchers.Matcher;
import com.googlecode.vmock.utils.Validate;

/**
 * A call intercepted in the recording stage. Unlike a call intercepted in {@link MockStage#REPLAYING} stage, it has matchers instead of call
 * parameters. This allows end-user to make a more flexible mocks.
 * 
 * @author marcin.jagus
 */
public class RecordedCall extends InterceptedCall {

    /**
     * Array of matchers.
     */
    private Matcher[] matchers;

    /**
     * Creates new recorded call based on a given intercepted call and an array of matchers.
     * 
     * @param call Intercepted call
     * @param matchers Array of matchers
     */
    public RecordedCall(InterceptedCall call, Matcher[] matchers) {
        this(call.getCaller(), call.getCallee(), call.getCallableObject(), matchers);
    }

    /**
     * Creates new recorded call
     * 
     * @param caller Object that made the call. Can be <code>null</code>.
     * @param callee Object which is the owner of called method/constructor. Can be <code>null</code>.
     * @param callableObject Either a method or a constructor. Never <code>null</code>.
     * @param matchers Array of matchers
     */
    public RecordedCall(Object caller, Object callee, AccessibleObject callableObject, Matcher[] matchers) {
        super(caller, callee, callableObject);

        setMatchers(matchers);
    }

    /**
     * Returns array of matchers for this call.
     * 
     * @return array of matchers for this call
     */
    public Matcher[] getMatchers() {
        return matchers;
    }

    /**
     * Setter with package visiblity to make the code easily testable.
     * 
     * @param matchers Matcher parameters of this call
     */
    void setMatchers(Matcher[] matchers) {
        Validate.notNull(matchers, "matchers == null");
        Validate.noNullElements(matchers, "There can me no null matchers");
        this.matchers = matchers;
    }

    @Override
    public String toString() {
        return String.format("RecordedCall{callTo: %s, caller: %s, callee: %s}", getCallableObject(), getCaller(), getCallee());
    }
}
